package org.bronycorps.mlptss.domain.actor;

import org.bronycorps.mlptss.domain.controller.AbstractController;
import org.bronycorps.mlptss.domain.controller.AbstractPlayerController;
import org.bronycorps.mlptss.domain.model.AbstractActorModel;
import org.bronycorps.mlptss.domain.model.Character.AnimationName;
import org.bronycorps.mlptss.domain.model.event.StateChangeEvent;
import org.bronycorps.mlptss.domain.model.event.StateChangeEventListener;
import org.bronycorps.mlptss.utils.AnimationCache;
import org.bronycorps.mlptss.utils.DrawableAnimation;

import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.Image;

public class PlayerActor extends AbstractGroupActor implements
		StateChangeEventListener {

	private DrawableAnimation chargeAnimation;
	private Image chargeImage;
	private float currentChargeTime;
	private DrawableAnimation hitAnimation;
	private AbstractPlayerController player;
	private DrawableAnimation slowAnimation;

	public PlayerActor(AbstractPlayerController player) {
		super();

		this.player = player;

		player.getModel().addListener(this);

		createAnimation();

		this.currentAnimation = this.slowAnimation;

		this.mainImage.setDrawable(this.currentAnimation
				.getDrawableKeyFrame(this.currentTime));
		this.mainImage.setWidth(this.mainImage.getPrefWidth());
		this.mainImage.setHeight(this.mainImage.getPrefHeight());
		setOrigin(getModelOrigin().x, getModelOrigin().y);

		this.hitBox.setWidth(getBounds().width);
		this.hitBox.setHeight(getBounds().height);
		player.getModel().setHitbox(this.relativeHitBox);

		this.chargeImage.setDrawable(this.chargeAnimation
				.getDrawableKeyFrame(this.currentChargeTime));

		this.chargeImage.setWidth(this.chargeImage.getPrefWidth());
		this.chargeImage.setHeight(this.chargeImage.getPrefHeight());
		this.chargeImage.setX(this.mainImage.getWidth());
		this.chargeImage.setY(this.mainImage.getHeight() / 2
				- this.chargeImage.getHeight() / 2);

		this.chargeImage.setVisible(false);

	}

	@Override
	public void act(float delta) {
		super.act(delta);
		this.currentChargeTime += delta;
		this.chargeImage.setVisible(this.player.getModel()
				.getSpecialAttackCharge() > 0.5);
	}

	private void createAnimation() {
		this.slowAnimation = AnimationCache.getInstance().get(
				this.player.getModel().getCharacter()
						.getAnimationName(AnimationName.FLY));
		this.hitAnimation = AnimationCache.getInstance().get(
				this.player.getModel().getCharacter()
						.getAnimationName(AnimationName.HIT));

		this.chargeAnimation = AnimationCache.getInstance().get(
				"default-charging");

	}

	@Override
	protected void drawFrame() {
		super.drawFrame();
		this.chargeImage.setDrawable(this.chargeAnimation
				.getDrawableKeyFrame(this.currentChargeTime));
	}

	public void fireBullet() {

	}

	@Override
	protected AbstractController getController() {
		return this.player;
	}

	@Override
	public AbstractActorModel getModel() {
		return this.player.getModel();
	}

	@Override
	public Vector2 getModelPosition() {

		Vector2 position = this.player.getModel().getPosition();

		Group parent = getParent();

		Rectangle pb = getBounds();

		position.x = Math.min(Math.max(getOriginX() - pb.x, position.x),
				parent.getWidth() + getOriginX() - pb.x - pb.width);
		position.y = Math.min(Math.max(getOriginY() - pb.y, position.y),
				parent.getHeight() + getOriginY() - pb.y - pb.height);

		return position;

	}

	public AbstractPlayerController getPlayer() {
		return this.player;
	}

	@Override
	protected void initializeChildren() {
		super.initializeChildren();
		this.chargeImage = new Image();

		addActor(this.chargeImage);
	}

	@Override
	public void onStateChange(StateChangeEvent event) {
		switch (event.getPlayer().getState()) {
		case HIT:
			switchAnimation(this.hitAnimation);
			break;
		case INVINCIBLE:
			getColor().a = 0.5f;
			break;
		default:
			setColor(1, 1, 1, 1);
			switchAnimation(this.slowAnimation);
			break;
		}

	}

}
